﻿using System;

namespace Space2D_Utils
{
	[Serializable]
	public struct Vector2d
	{
		public Vector2d(Vector2d vec)
			: this()
		{
			Set(vec);
		}

		public Vector2d(Vector2d dir, double magnitude)
			: this()
		{
			Set(dir.Normalized() * magnitude);
		}

		public Vector2d(double x, double y)
			: this()
		{
			Set(x, y);
		}

		public void Set(Vector2d vec)
		{
			Set(vec.X, vec.Y);
		}

		public void Set(double x, double y)
		{
			X = x;
			Y = y;

			SqrLength = X * X + Y * Y;
			SqrtLength = Math.Sqrt(SqrLength);
		}

		/*public void Normalize()
		{
			if (SqrtLength <= 0.0)
			{
				Set(0, 0);
			}
			else
			{
				double x = X / SqrtLength;
				double y = Y / SqrtLength;

				Set(x, y);
			}
		}*/

		public Vector2d Normalized()
		{
			return new Vector2d(X / SqrtLength, Y / SqrtLength);
		}

		public static double SqrDistance(Vector2d v1, Vector2d v2)
		{
			double dx = v1.X - v2.X;
			double dy = v1.Y - v2.Y;

			return dx * dx + dy * dy;
		}

		public static Vector2d Direction(Vector2d v1, Vector2d v2)
		{
			Vector2d dir = new Vector2d(v1.X - v2.X, v1.Y - v2.Y);

			return dir.Normalized();
		}

		public static double Distance(Vector2d v1, Vector2d v2)
		{
			return Math.Sqrt(SqrDistance(v1, v2));
		}

		public static bool operator ==(Vector2d a, Vector2d b)
		{
			if (System.Object.ReferenceEquals(a, b))
			{
				return true;
			}

			return a.X == b.X && a.Y == b.Y;
		}

		public static bool operator !=(Vector2d a, Vector2d b)
		{
			if (System.Object.ReferenceEquals(a, b))
			{
				return true;
			}

			return a.X != b.X || a.Y != b.Y;
		}

		public override bool Equals(object obj)
		{
			return base.Equals(obj);
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		public override string ToString()
		{
			return "X " + X + ", Y " + Y;
		}

		public static Vector2d operator -(Vector2d a)
		{
			return new Vector2d(-a.X, -a.Y);
		}

		public static Vector2d operator +(Vector2d a, Vector2d b)
		{
			return new Vector2d(a.X + b.X, a.Y + b.Y);
		}

		public static Vector2d operator -(Vector2d a, Vector2d b)
		{
			return new Vector2d(a.X - b.X, a.Y - b.Y);
		}

		public static Vector2d operator *(Vector2d a, double b)
		{
			return new Vector2d(a.X * b, a.Y * b);
		}

		public static Vector2d operator *(double b, Vector2d a)
		{
			return new Vector2d(a.X * b, a.Y * b);
		}

		public static Vector2d operator /(Vector2d a, double b)
		{
			return new Vector2d(a.X / b, a.Y / b);
		}

		public double X { get; private set; }
		public double Y { get; private set; }
		public double SqrLength { get; private set; }
		public double SqrtLength { get; private set; }
	}
}
